package com.wande.dataplatform.filecollection.parser;

import cn.hutool.core.util.StrUtil;
import com.wande.dataplatform.filecollection.common.enums.FileCollectionErrorCode;
import com.wande.dataplatform.filecollection.common.exception.FileCollectionException;
import com.wande.dataplatform.filecollection.domain.dto.FieldInfo;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Pattern;

/**
 * 文件解析器抽象基类
 * 提供通用的解析逻辑和工具方法
 *
 * @author dataplatform
 * @date 2025-01-24
 */
@Slf4j
public abstract class AbstractFileParser implements IFileParser {

    /**
     * 数字正则表达式
     */
    private static final Pattern NUMBER_PATTERN = Pattern.compile("^-?\\d+(\\.\\d+)?$");

    /**
     * 整数正则表达式
     */
    private static final Pattern INTEGER_PATTERN = Pattern.compile("^-?\\d+$");

    /**
     * 日期正则表达式（yyyy-MM-dd）
     */
    private static final Pattern DATE_PATTERN = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$");

    /**
     * 时间戳正则表达式（yyyy-MM-dd HH:mm:ss）
     */
    private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$");

    /**
     * 布尔值集合
     */
    private static final Set<String> BOOLEAN_TRUE_VALUES = new HashSet<>(Arrays.asList("true", "yes", "1", "y", "t"));
    private static final Set<String> BOOLEAN_FALSE_VALUES = new HashSet<>(Arrays.asList("false", "no", "0", "n", "f"));

    @Override
    public void parseStream(InputStream inputStream, ParserConfig config, Consumer<Map<String, Object>> consumer) {
        // 默认实现：使用迭代器模式
        Iterator<Map<String, Object>> iterator = parse(inputStream, config);
        while (iterator.hasNext()) {
            consumer.accept(iterator.next());
        }
    }

    /**
     * 推断字段类型
     *
     * @param value 字段值
     * @return 字段类型
     */
    protected String inferFieldType(String value) {
        if (StrUtil.isBlank(value)) {
            return "STRING";
        }

        value = value.trim();

        // 布尔类型
        if (BOOLEAN_TRUE_VALUES.contains(value.toLowerCase()) || 
            BOOLEAN_FALSE_VALUES.contains(value.toLowerCase())) {
            return "BOOLEAN";
        }

        // 整数类型
        if (INTEGER_PATTERN.matcher(value).matches()) {
            try {
                Long.parseLong(value);
                return "LONG";
            } catch (NumberFormatException e) {
                return "STRING";
            }
        }

        // 数字类型
        if (NUMBER_PATTERN.matcher(value).matches()) {
            try {
                new BigDecimal(value);
                return "DOUBLE";
            } catch (NumberFormatException e) {
                return "STRING";
            }
        }

        // 时间戳类型
        if (TIMESTAMP_PATTERN.matcher(value).matches()) {
            return "TIMESTAMP";
        }

        // 日期类型
        if (DATE_PATTERN.matcher(value).matches()) {
            return "DATE";
        }

        return "STRING";
    }

    /**
     * 推断多个样本值的字段类型
     *
     * @param samples 样本值列表
     * @return 字段类型
     */
    protected String inferFieldTypeFromSamples(List<String> samples) {
        if (samples == null || samples.isEmpty()) {
            return "STRING";
        }

        Map<String, Integer> typeCount = new HashMap<>();
        for (String sample : samples) {
            if (StrUtil.isNotBlank(sample)) {
                String type = inferFieldType(sample);
                typeCount.put(type, typeCount.getOrDefault(type, 0) + 1);
            }
        }

        // 返回出现次数最多的类型
        return typeCount.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse("STRING");
    }

    /**
     * 转换字段值
     *
     * @param value 原始值
     * @param targetType 目标类型
     * @param dateFormat 日期格式
     * @return 转换后的值
     */
    protected Object convertValue(String value, String targetType, String dateFormat) {
        if (StrUtil.isBlank(value)) {
            return null;
        }

        value = value.trim();

        try {
            switch (targetType.toUpperCase()) {
                case "STRING":
                    return value;
                case "INTEGER":
                    return Integer.parseInt(value);
                case "LONG":
                    return Long.parseLong(value);
                case "DOUBLE":
                    return Double.parseDouble(value);
                case "BOOLEAN":
                    return BOOLEAN_TRUE_VALUES.contains(value.toLowerCase());
                case "DATE":
                case "TIMESTAMP":
                    SimpleDateFormat sdf = new SimpleDateFormat(dateFormat != null ? dateFormat : "yyyy-MM-dd HH:mm:ss");
                    return sdf.parse(value);
                default:
                    return value;
            }
        } catch (NumberFormatException | ParseException e) {
            log.warn("Failed to convert value '{}' to type '{}': {}", value, targetType, e.getMessage());
            return value;
        }
    }

    /**
     * 清理字段名称
     * 去除特殊字符，转换为合法的字段名
     *
     * @param fieldName 原始字段名
     * @return 清理后的字段名
     */
    protected String cleanFieldName(String fieldName) {
        if (StrUtil.isBlank(fieldName)) {
            return "field_" + System.currentTimeMillis();
        }

        // 去除前后空格
        fieldName = fieldName.trim();

        // 替换特殊字符为下划线
        fieldName = fieldName.replaceAll("[^a-zA-Z0-9_\\u4e00-\\u9fa5]", "_");

        // 如果以数字开头，添加前缀
        if (Character.isDigit(fieldName.charAt(0))) {
            fieldName = "field_" + fieldName;
        }

        return fieldName;
    }

    /**
     * 处理字段值
     * 根据配置进行去空格等处理
     *
     * @param value 原始值
     * @param config 解析器配置
     * @return 处理后的值
     */
    protected String processFieldValue(String value, ParserConfig config) {
        if (value == null) {
            return null;
        }

        if (config.getTrimFields() != null && config.getTrimFields()) {
            value = value.trim();
        }

        return value;
    }

    /**
     * 检查是否为空行
     *
     * @param record 记录数据
     * @return 是否为空行
     */
    protected boolean isEmptyRow(Map<String, Object> record) {
        if (record == null || record.isEmpty()) {
            return true;
        }

        return record.values().stream()
                .allMatch(value -> value == null || StrUtil.isBlank(value.toString()));
    }

    /**
     * 验证输入流
     *
     * @param inputStream 输入流
     */
    protected void validateInputStream(InputStream inputStream) {
        if (inputStream == null) {
            throw new FileCollectionException(FileCollectionErrorCode.INVALID_PARAMETER, "Input stream cannot be null");
        }
    }

    /**
     * 验证解析器配置
     *
     * @param config 解析器配置
     */
    protected void validateConfig(ParserConfig config) {
        if (config == null) {
            throw new FileCollectionException(FileCollectionErrorCode.INVALID_PARAMETER, "Parser config cannot be null");
        }
    }

    /**
     * 创建字段信息
     *
     * @param fieldName 字段名
     * @param fieldType 字段类型
     * @param fieldIndex 字段索引
     * @return 字段信息
     */
    protected FieldInfo createFieldInfo(String fieldName, String fieldType, Integer fieldIndex) {
        return FieldInfo.builder()
                .fieldName(fieldName)
                .fieldType(fieldType)
                .fieldIndex(fieldIndex)
                .nullable(true)
                .build();
    }

    /**
     * 记录解析错误
     *
     * @param recordIndex 记录索引
     * @param fieldName 字段名
     * @param errorMessage 错误消息
     */
    protected void logParseError(Integer recordIndex, String fieldName, String errorMessage) {
        log.warn("Parse error at record {}, field '{}': {}", recordIndex, fieldName, errorMessage);
    }
}
